#ifndef BANK_TABLE_H
#define BANK_TABLE_H

#include <string>
#include <sqlite3.h>

class BankDatabase
{
public:
  BankDatabase ();
  virtual ~BankDatabase ();
  /**
   * Get access to the BankDatabase in the database
   * 
   * \param dbName the file name of the database
   */
  BankDatabase (std::string dbName);
  /**
   * Open a connection to get access to the BankDatabase in the database
   * 
   * \param dbName the file name of the database
   */
  void Open (std::string dbName);
  /**
   * Close the connection to the database and free up all prepared statement
   */
  void Close ();
  /// get the filename of the database file
  std::string GetDatabaseName () const;

  /**
   * Create a customer if it does not exist, or do nothing if it already existed
   *
   * \param cusId the ID of a customer
   */
  void TouchCustomer (std::string cusId);

  /**
   * Set the balance of a customer. If the customer does not exist, create it.
   *
   * \param cusId customer ID
   * \param balance the new balance for the customer
   */
  void SetBalance (std::string cusId, double balance);

  /**
   * Get the balance of a customer. If the customer does not exist, return 0
   * and do not create it.
   *
   * \param cusId customer ID
   * \return balance of the customer
   */
  double GetBalance (std::string cusId);

  /**
   * Start a transaction on this database
   */
  void BeginTransaction ();
  
  /**
   * Commit an opened transaction
   *
   * \return true if commit is done successfully; false otherwise
   */
  bool CommitTransaction ();

  /** 
   * Rollback an opened transaction
   *
   * \return true if rollback is done successfully; false otherwise
   */
  bool RollbackTransaction ();

  /**
   * Get the UpdateCount as seen by a client
   *
   * \param clientId ID of a client
   * \return the UpdateCount of the client
   */
  int GetUpdateCount (std::string clientId);

  /**
   * Increment the UpdateCount of a client by 1
   *
   * \param clientId ID of a client
   */
  void IncrementUpdateCount (std::string clientId);

private:
  /// handle to the database connection
  sqlite3* m_db;
  /// filename of bank database file
  std::string m_dbName;

  /// prepared sqlite3 statement for reading balance of a customer
  sqlite3_stmt* m_getBalanceStmt;
  /// prepared sqlite3 statement for setting balance of a customer
  sqlite3_stmt* m_setBalanceStmt;

  /// prepared sqlite3 statement for reading UpdateCount
  sqlite3_stmt* m_getUpdateCountStmt;
  /// prepared sqlite3 statement for setting UpdateCount
  sqlite3_stmt* m_setUpdateCountStmt;
  /// prepared sqlite3 statement for touching a customer
  sqlite3_stmt* m_touchCustomerStmt;
  /// true if a db connection is created; false otherwise
  bool m_dbIsOpened;
};

#endif // ifndef BANK_TABLE_H
